<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */
declare (strict_types=1);

namespace app\index\controller;

use app\BaseController;
use app\index\model\{Configuration,
    MembershipLevel,
    MembershipPresent,
    MembershipRecord,
    Order,
    OrderCommodity,
    RechargeRecord,
    User,
    UserCash,
    OrderCommodityAttach,
    GroupCommodity,
    Collage,
    CollageItem,
    ActivityRecharge,
    UserCoupon
};
use app\index\service\ReceiptsService;
use app\index\util\Inventory;
use app\index\util\Redis;
use app\utils\{Addons, SendMsg};
use think\App;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\db\Query;
use think\Exception;
use think\exception\HttpException;
use think\facade\Cache;
use think\facade\Db;
//use think\facade\View;


class Notify extends BaseController
{

    private $xml;
    private $redis;


    protected function xmlToArr($xml)
    {
        libxml_disable_entity_loader(true);
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }

    public function __construct(App $app)
    {
        parent::__construct($app);
        $xml = file_get_contents('php://input');
        if (!empty($xml)) {
            $this->xml = $this->xmlToArr($xml);
        } else {
            throw new HttpException(HTTP_INVALID, '');
        }
        $this->redis = Redis::getInstance();
    }

    public function commodity()
    {
        $trade = $this->xml['out_trade_no'];
        $payNo = $this->xml['transaction_id'];

        $order = Order::withoutGlobalScope(['userId'])->where(['unified_order_no' => $trade])->lock(true)
                ->find();
        $attach = $order['user_id'];

        if (!$order) {
            return false;
        }
        global $mid;
        $mid = $order->mall_id;

        $flag = $this->redis->lPop("ORDER:" . $trade);
        if ($flag == 1) {
            Db::startTrans();
            try {
                //TODO 参数校验
                Order::withoutGlobalScope(['userId'])->where(['unified_order_no' => $trade])->update(['status' => 2, 'pay_no' => $payNo, 'settlement' => 1]);
                $column = Order::withoutGlobalScope(['userId'])->where(['unified_order_no' => $trade])->column('id');
                if ($order['has_attach'] == 1) {
                    OrderCommodityAttach::update(['status' => 1], ['order_id' => $order['id']]);
                }
                //支付减库存
                Inventory::sub($column);
                OrderCommodity::update(['status' => 2], ['order_id' => $column]);
                Db::commit();
            } catch (\Exception $e) {
                Db::rollback();
                $this->redis->lpush("ORDER:" . $trade, 1);
                return false;
            }
        }
        // 拼团
        $oc = OrderCommodity::where(['order_id' => $column])->find();
        if ($oc['gc_id'] != 0) {
            Collage::createCollage($oc['id'], $attach);
        }

        $user = \app\index\model\User::find($attach);
        \app\utils\Agent::upgrade($user);
        \app\utils\Agent::bindingPid($user);
        \app\index\util\Lottery::setUserLottery($user, $order->money);
        try {
            $check = Addons::check($user->mall_id, 4);
            if ($check) {

                $url = $user->UserWx->type == 1 ?
                    url("/orderpage/order/list", ['tab' => 2, 'mall_id' => $user->mall_id], false, false)->build() :
                    url("/h5/#/orderpage/order/list", ['tab' => 2, 'mall_id' => $user->mall_id], false, true)->build();
                $msgData = Cache::get(checkRedisKey("MSGDATA:PAY:" . $attach));
                $sendMsg = new SendMsg("订单支付通知");
                $sendMsg->send($user, $msgData, $url);
                $sendMsg = new SendMsg("订单付款通知");
                $msgData['order_commodity'] = "余额下单";
                $msgData['buyer_name'] = $user->nickname;
                $msgData['buyer_mobile'] = $user->mobile;
                $sendMsg->send($user, $msgData, $url);
            }
        } catch (\Exception $e) {

        }

        $check = Addons::check($user->mall_id, 10);
        if ($check) {
            $receipts = new ReceiptsService();
            $receipts->printer(0, 'pay', $payNo);
        }
        try {
            //检测是否可升级会员等级
            $this->upgradeMemberLevel($order->base_in, $user);
        } catch (\Exception $e) {
            
        }
        return $this->ToXml();
    }

    public function webcommodity()
    {
        Db::name('advert')->insert(['content' => serialize($this->xml)]);
//        $openid = $this->xml['openid'];
//        {
//            "appid": "wx9520cb5db0b78c62",
//    "bank_type": "OTHERS",
//    "cash_fee": "1",
//    "fee_type": "CNY",
//    "is_subscribe": "Y",
//    "mch_id": "1543491821",
//    "nonce_str": "tha479ptqcfxwghxl1rt90192qdugrsi",
//    "openid": "ok2he1CWN6_aJjoufqc8E2eUniXI",
//    "out_trade_no": "16482654785273120521463027",
//    "result_code": "SUCCESS",
//    "return_code": "SUCCESS",
//    "sign": "D90C5971213756631200750B46AEB5E5",
//    "time_end": "20220326113123",
//    "total_fee": "1",
//    "trade_type": "MWEB",
//    "transaction_id": "4200001392202203269715534348"
//}
        $trade = $this->xml['out_trade_no'];
        $payNo = $this->xml['transaction_id'];


        $order = Order::withoutGlobalScope(['userId'])->where(['unified_order_no' => $trade])->lock(true)
            ->find();
        if (!$order) {
            return false;
        }
        global $mid;
        $mid = $order->mall_id;

        $flag = $this->redis->lPop("ORDER:" . $trade);
        if ($flag == 1) {
            Db::startTrans();
            try {
                //TODO 参数校验
                Order::withoutGlobalScope(['userId'])->where(['unified_order_no' => $trade])->update(['status' => 2, 'pay_no' => $payNo, 'settlement' => 1]);
                $column = Order::withoutGlobalScope(['userId'])->where(['unified_order_no' => $trade])->column('id');
                if ($order['has_attach'] == 1) {
                    OrderCommodityAttach::update(['status' => 1], ['order_id' => $order['id']]);
                }
                //支付减库存
                Inventory::sub($column);
                OrderCommodity::update(['status' => 2], ['order_id' => $column]);
                Db::commit();
            } catch (\Exception $e) {
                Db::rollback();
                $this->redis->lpush("ORDER:" . $trade, 1);
                return false;
            }
        }
        $user = \app\index\model\User::find($order->user_id);
        $check = Addons::check($user->mall_id, 4);
        \app\utils\Agent::upgrade($user);
        \app\utils\Agent::bindingPid($user);
        \app\index\util\Lottery::setUserLottery($user, $order->money);
        if ($check) {

            $url = $user->UserWx->type == 1 ?
                url("/orderpage/order/list", ['tab' => 2, 'mall_id' => $user->mall_id], false, false)->build() :
                url("/h5/#/orderpage/order/list", ['tab' => 2, 'mall_id' => $user->mall_id], false, true)->build();
            $msgData = Cache::get(checkRedisKey("MSGDATA:PAY:" . $order->user_id));
            $sendMsg = new SendMsg("订单支付通知");
            $sendMsg->send($user, $msgData, $url);
        }
        $check = Addons::check($user->mall_id, 10);
        if ($check) {
            $receipts = new ReceiptsService();
            $receipts->printer(0, 'pay', $payNo);
        }
        try {
            //检测是否可升级会员等级
            $this->upgradeMemberLevel($order->base_in, $user);
        } catch (\Exception $e) {

        }
        return $this->ToXml();
    }

    public function upgradeMemberLevel($baseIn, $orderUser)
    {
        global $user, $mid;
        $user = User::find($orderUser->id);
        $mid = $user->mall_id;
        if (!Addons::check($user->mall_id, 20)) {
            return false;
        }

        $memberLevelConfig = Configuration::where(['type' => 'memberLevel'])->value('configuration');
        if (!$memberLevelConfig) {
            return false;
        }
        $memberLevelConfig = json_decode($memberLevelConfig, true);
        if (empty($memberLevelConfig['is_open'])) {
            return false;
        }

        empty($user->level_time) && $create_time = '2022-01-01';
        $money = Order::where('user_id',$user->id)
            ->where('status',4)
            ->where('create_time',$create_time ?? $user->level_time)
            ->sum('money');

        if (empty($money)){
            return false;
        }
        $money = bcsub((string)$countMoney['order_money'], (string)$countMoney['refund_money']);

        $membershipLevelList = MembershipLevel::where(
            [
                ['level', '>', $user->level],
                ['is_cash_upgrade', '=', 1],
                ['reach_cash', '<', $money],
            ])
            ->where(function (Query $query) {
                $query->whereOr([
                    ['is_present_money', '=', 1],
                    ['is_present_integer', '=', 1],
                    ['is_present_coupon', '=', 1],
                ]);
            })
            ->order('level', 'asc')
            ->select();

        if ($membershipLevelList->isEmpty()) {
            return false;
        }

        $record = [
            'mall_id' => $user->mall_id,
            'user_id' => $user->id,
            'base_in' => $baseIn,
            'source_type' => 2,
            'source' => "用户满足指定金额升级",
            'old_level' => $user->level,
            'new_level' => $membershipLevelList[count($membershipLevelList) - 1]->level,
            'status' => 1
        ];

        Db::startTrans();
        try {

            //变更会员等级
            User::update(['level' => $record['new_level'], 'level_time' => date('Y-m-d H:i:s')], ['id' => $user->id]);

            //添加记录
            $membershipRecord = MembershipRecord::create($record);

            $presentMoney = 0;
            $presentInteger = 0;
            $presentCoupon = [];

            //添加礼物记录
            foreach ($membershipLevelList as $k => $v) {
                $presentRecord = array();
                if (!empty($v['is_present_money'])) {
                    $presentRecord['present_money'] = $v['present_money'];
                    $presentMoney = bcadd((string)$presentMoney, (string)$v['present_money']);
                }
                if (!empty($v['is_present_integer'])) {
                    $presentRecord['present_integer'] = $v['present_integer'];
                    $presentInteger = bcadd((string)$presentInteger, (string)$v['present_integer']);
                }
                if (!empty($v['is_present_coupon'])) {
                    $couponIds = explode(',', $v['present_coupon']);
                    $couponList = \app\index\model\Coupon::where(['id' => $couponIds])
                        ->field('*')
                        ->select();
                    if (!$couponList->isEmpty()) {
                        $couponList->toArray();
                    }
                    $presentRecord['present_coupon'] = $couponList;
                    $presentCoupon = array_merge($presentCoupon, $couponIds);

                }
                $presentRecord['record_id'] = $membershipRecord->id;
                $presentRecord['level'] = $v->level;
                MembershipPresent::create($presentRecord);


            }
            //发放礼物
            if (!empty($presentMoney) || !empty($presentInteger)) {
                UserCash::where("user_id", $record['user_id'])
                    ->inc("recharge", (double)$presentMoney)
                    ->inc("total", (double)$presentMoney)
                    ->inc("integral", (double)$presentInteger)
                    ->inc("integral_total", (double)$presentInteger)
                    ->update();
            }
            if (!empty($presentCoupon)) {
                $userCouponService = new UserCouponService();
                foreach ($presentCoupon as $couponId) {
                    try {
                        $userCouponService->save((int)$couponId);
                    } catch (DataNotFoundException $e) {
                    } catch (ModelNotFoundException $e) {
                    } catch (DbException $e) {
                    } catch (Exception $e) {
                    }
                }
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            return false;
        }

        return true;

    }

    public function recharge()
    {
        $trade = $this->xml['out_trade_no'];
        $payNo = $this->xml['transaction_id'];
        $record = $this->redis->lPop("RECHARGE:" . $trade);
        if (empty($record)) {
            return false;
        }
        $record = json_decode($record, true);
        Db::startTrans();
        try {

            $userCash = UserCash::where("user_id", $record['user_id'])
                ->lock(true)
                ->find();

            $newData = ['status' => 1, 'pay_no' => $payNo, "old_cash" => $userCash->total, "new_cash" => bcadd((string)$userCash->total, (string)$record['money'])];
            $newRecord = array_merge($record, $newData);

            RechargeRecord::create($newRecord);
            UserCash::where("user_id", $record['user_id'])
                ->inc("recharge", (double)$record['money'])
                ->inc("total", (double)$record['money'])
                ->update();
            Db::commit();

        } catch (\Exception $e) {
            Db::rollback();
            $this->redis->lpush("RECHARGE:" . $trade, $record);
            return false;
        }

        $user = User::find($record['user_id']);
        // 充值奖励
        $checkRecharge = Addons::check($user->mall_id, 36);
        if ($checkRecharge) {
            $where = [
                'status' => 1,
                'mall_id' => $user->mall_id,
                'single_recharge' => $record['money']
            ];
            $recharge = ActivityRecharge::where($where)->find();
            if (!empty($recharge)) {
                $rewardsType = json_decode($recharge['rewards_type'], true);
                foreach ($rewardsType as $key => $value) {
                    // 1优惠券，2积分，3余额
                    switch ($value) {
                        case 1:
                            try {
                                Db::startTrans();
                                $coupons = json_decode($recharge['coupon'], true);
                                if (is_array($coupons)) {
                                    foreach ($coupons as $ck => $cv) {
                                        UserCoupon::giveUserCoupon($cv, $user->id);
                                    }
                                }
                                Db::commit();
                            } catch (\Exception $e) {
//                                var_dump($e->getMessage());
                                Db::rollback();
                            }
                            break;
                        case 2:
                            $credit = $recharge['credit'];
                            try {
                                Db::startTrans();
                                UserCash::giveIntegral($user['id'], $credit, 16, $user['mall_id']);
                                Db::commit();
                            } catch (\Exception $e) {
//                                var_dump($e->getMessage());
                                Db::rollback();
                            }
                            break;
                        case 3:
                            $balance = $recharge['balance'];
                            try {
                                Db::startTrans();
                                global $baseIn;
                                $userCash = UserCash::where("user_id", $user['id'])
                                    ->lock(true)
                                    ->find();
                                $data = [
                                    'mall_id' => $user['mall_id'],
                                    'user_id' => $user['id'],
                                    'base_in' => $baseIn,
                                    'source_type' => 14,
                                    'source' => "充值".$record['money']."赠送".$balance."元",
                                    'is_online' => 0,
                                    'type' => 0,
                                    'money' => $balance,
                                    'status' => 1,
                                    'pay_no' => $payNo,
                                    "old_cash" => $userCash->total,
                                    "new_cash" => bcadd((string)$userCash->total, (string)$balance),
                                    'create_time' => date("Y-m-d H:i:s", time())
                                ];
                                $userCash->inc("total", $balance)
                                    ->update();
                                RechargeRecord::create($data);
                                Db::commit();
                            } catch (\Exception $e) {
//                                var_dump($e->getMessage());
                                Db::rollback();
                            }
                            break;
                    }
                }
            }
        }
        // 模版消息
        $check = Addons::check($user->mall_id, 4);
        if ($check) {
            $msgData = [
                'recharge_user' => $record['user_id'],
                'recharge_reality_cash' => $record['money'],
                'recharge_type' => "微信支付",
                'recharge_time' => date("Y-m-d H:i:s", time())
            ];
            $sendMsg = new SendMsg("充值成功通知");
            $url = $user->UserWx->type == 1 ?
                "/pages/mine/mine" :
                request()->domain() . "/h5/#/pages/mine/mine";
            $sendMsg->send($user, $msgData, $url);
        }
        return $this->ToXml();
    }


    public function membership()
    {
        $openid = $this->xml['openid'];
        $attach = $this->xml['attach'];
        $trade = $this->xml['out_trade_no'];
        $payNo = $this->xml['transaction_id'];

        $recordData = $this->redis->lPop("MEMBERSHIP:" . $trade);
        $record = json_decode($recordData, true);
        $mid = $record['mall_id'];
        $record['pay_no'] = $payNo;

        if (empty($recordData)) {
            return false;
        }
        $user = User::find($attach);
        if (!$user->isEmpty()) {
            $user = $user->toArray();
        } else {
            return false;
        }
        $config = new Configuration(['mall_id' => $mid]);
        $memberLevelConfig = $config->where(['type' => 'memberLevel'])->value('configuration');
        if (!$memberLevelConfig) {
            return false;
        }
        $memberLevelConfig = json_decode($memberLevelConfig, true);
        $level = MembershipLevel::where('level', $record['level_id'])->find();
        if (empty($memberLevelConfig['is_open']) && empty($level)) {
            return false;
        }
        Db::startTrans();
        try {
            //变更会员等级
            User::update(['level' => $record['new_level'], 'level_time' => date('Y-m-d H:i:s', strtotime("+".$level['indate']." day"))], ['id' => $attach]);

            //添加记录
            $membershipRecord = MembershipRecord::create($record);

            //下发奖励
            $membershipLevelList = MembershipLevel::where(
                [
                    ['level', 'between', [$record['old_level'], $record['new_level']]],
                    ['is_buy_upgrade', '=', 1]
                ])
                ->where(function (Query $query) {
                    $query->whereOr([
                        ['is_present_money', '=', 1],
                        ['is_present_integer', '=', 1],
                        ['is_present_coupon', '=', 1],
                    ]);
                })
                ->order('level', 'asc')
                ->select();
            if (!$membershipLevelList->isEmpty()) {
                $presentMoney = 0;
                $presentInteger = 0;
                $presentCoupon = [];

                //添加礼物记录
                foreach ($membershipLevelList as $k => $v) {
                    $presentRecord = array();
                    if (!empty($v['is_present_money'])) {
                        $presentRecord['present_money'] = $v['present_money'];
                        $presentMoney = bcadd((string)$presentMoney, (string)$v['present_money']);
                    }
                    if (!empty($v['is_present_integer'])) {
                        $presentRecord['present_integer'] = $v['present_integer'];
                        $presentInteger = bcadd((string)$presentInteger, (string)$v['present_integer']);
                    }
                    if (!empty($v['is_present_coupon'])) {
                        $couponIds = explode(',', $v['present_coupon']);
                        $couponList = \app\index\model\Coupon::where(['id' => $couponIds])
                            ->field('*')
                            ->select();
                        if (!$couponList->isEmpty()) {
                            $couponList->toArray();
                        }
                        $presentRecord['present_coupon'] = $couponList;
                        $presentCoupon = array_merge($presentCoupon, $couponIds);

                    }
                    $presentRecord['record_id'] = $membershipRecord->id;
                    $presentRecord['level'] = $v->level;
                    MembershipPresent::create($presentRecord);
                }

                //发放礼物
                if (!empty($presentMoney) || !empty($presentInteger)) {
                    UserCash::where("user_id", $record['user_id'])
                        ->inc("recharge", (double)$presentMoney)
                        ->inc("total", (double)$presentMoney)
                        ->inc("integral", (double)$presentInteger)
                        ->inc("integral_total", (double)$presentInteger)
                        ->update();
                }
                if (!empty($presentCoupon)) {
                    $userCouponService = new UserCouponService();
                    foreach ($presentCoupon as $couponId) {
                        try {
                            $userCouponService->save((int)$couponId);
                        } catch (DataNotFoundException $e) {
                        } catch (ModelNotFoundException $e) {
                        } catch (DbException $e) {
                        } catch (Exception $e) {
                        }
                    }
                }
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->redis->lpush("MEMBERSHIP:" . $trade, $recordData);
            return false;
        }

        return $this->ToXml();
    }


    public function ToXml()
    {
        $xml = "<xml>
                  <return_code><![CDATA[SUCCESS]]></return_code>
                  <return_msg><![CDATA[OK]]></return_msg>
                </xml>";
        return $xml;
    }


//    public function isPay()
//    {
//        var_dump(33);die();
//        header('Content-Type: application/vnd.ms-excel');
//        // 渲染模板输出
//        return View::fetch('index');
//    }

}
